import 'dart:math';

import 'package:flutter/material.dart';

class RedDotPage extends StatefulWidget {
  final Offset startPosition;
  final Offset endPosition;

  const RedDotPage(
      {Key? key, required this.startPosition, required this.endPosition})
      : super(key: key);

  @override
  _RedDotPageState createState() => _RedDotPageState();
}

class _RedDotPageState extends State<RedDotPage>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller; // 动画 controller
  late Animation<double> _animation; // 动画
  late double left; // 小圆点的left（动态计算）
  late double top; // 小远点的right（动态计算）
  // 二阶贝塞尔曲线用值
  late double x0 = widget.startPosition.dx;
  late double y0 = widget.startPosition.dy;

  late double x1 = widget.startPosition.dx - 250;
  late double y1 = widget.startPosition.dy - 100;

  late double x2 = widget.endPosition.dx;
  late double y2 = widget.endPosition.dy;

  @override
  void initState() {
    super.initState();
    _controller =
        AnimationController(duration: Duration(milliseconds: 800), vsync: this);
    _animation = Tween(begin: 0.0, end: 1.0).animate(_controller);

    // 初始化小圆点的位置
    left = widget.startPosition.dx;
    top = widget.startPosition.dy;

    // 显示小圆点的时候动画就开始
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    // 用 Stack -> Positioned 来控制小圆点的位置
    return Stack(
      children: <Widget>[
        AnimatedBuilder(
          animation: _animation,
          builder: (BuildContext context, Widget? child) {
            // t 动态变化的值
            var t = _animation.value;
            if (mounted) {
              left = pow(1 - t, 2) * x0 + 2 * t * (1 - t) * x1 + pow(t, 2) * x2;
              top = pow(1 - t, 2) * y0 + 2 * t * (1 - t) * y1 + pow(t, 2) * y2;
            }
            return Positioned(
              left: left,
              top: top,
              child: ClipOval(
                child: Container(
                  width: 14,
                  height: 14,
                  color: Colors.red,
                ),
              ),
            );
          },
        )
      ],
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}
